package site.addzero.cli.autoinit.windows

import org.koin.core.annotation.Single
import site.addzero.cli.platform.PlatformTools
import site.addzero.cli.platform.PlatformType
import site.addzero.cli.platform.runCmd
import site.addzero.cli.setting.SettingContext
import site.addzero.task.InitTask
import java.io.File

/**
 * Windows 平台 Zulu JDK 自动初始化类
 * 负责下载 Zulu JDK 8, 17, 21 并配置 JAVA_HOME
 */
@Single
class AutoInitZuluJdkWin : InitTask {
    override val support: Boolean = isWindowsPlatform()

    // Zulu JDK 下载 URLs for Windows
    private fun getZuluJdkUrls(): Map<Int, String> {
        val arch = System.getProperty("os.arch")
        val isArm = arch.contains("aarch64") || arch.contains("arm")

        return mapOf(
            8 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-win_aarch64.zip" 
                else "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-win_x64.zip",
            17 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-win_aarch64.zip" 
                else "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-win_x64.zip",
            21 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-win_aarch64.zip" 
                else "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-win_x64.zip"
        )
    }

    private fun getZuluJdkFilenames(): Map<Int, String> {
        val arch = System.getProperty("os.arch")
        val isArm = arch.contains("aarch64") || arch.contains("arm")

        return mapOf(
            8 to if (isArm) "zulu8.76.0.17-ca-jdk8.0.402-win_aarch64.zip" 
                else "zulu8.76.0.17-ca-jdk8.0.402-win_x64.zip",
            17 to if (isArm) "zulu17.48.15-ca-jdk17.0.10-win_aarch64.zip" 
                else "zulu17.48.15-ca-jdk17.0.10-win_x64.zip",
            21 to if (isArm) "zulu21.36.17-ca-jdk21.0.6-win_aarch64.zip" 
                else "zulu21.36.17-ca-jdk21.0.6-win_x64.zip"
        )
    }

    /**
     * 执行 Zulu JDK 初始化任务
     */
    override suspend fun asynctask(): Boolean {
        if (!support) {
            println("当前平台不支持 Zulu JDK 自动初始化")
            return true
        }

        println("正在初始化 Zulu JDK (Windows)...")

        // 确保 useful 目录存在
        val usefulDir = File(SettingContext.USEFUL_SOFT_DIR)
        if (!usefulDir.exists()) {
            usefulDir.mkdirs()
        }

        // 获取平台相关的下载 URLs
        val zuluJdkUrls = getZuluJdkUrls()
        val zuluJdkFilenames = getZuluJdkFilenames()

        // 下载并解压各个版本的 JDK
        val installedJdks = mutableMapOf<Int, String>()
        for ((version, url) in zuluJdkUrls) {
            try {
                val filename = zuluJdkFilenames[version] ?: continue
                val jdkPath = downloadAndExtractJdk(version, url, filename, usefulDir.absolutePath)
                if (jdkPath != null) {
                    installedJdks[version] = jdkPath
                    println("Zulu JDK $version 安装成功: $jdkPath")
                } else {
                    println("Zulu JDK $version 安装失败")
                }
            } catch (e: Exception) {
                println("安装 Zulu JDK $version 时出错: ${e.message}")
            }
        }

        // 配置 JAVA_HOME 为 JDK 17
        if (installedJdks.containsKey(17)) {
            configureJavaHome(installedJdks[17]!!)
        } else if (installedJdks.isNotEmpty()) {
            // 如果没有 JDK 17，使用第一个安装的版本
            val firstJdk = installedJdks.values.first()
            configureJavaHome(firstJdk)
        }

        return true
    }

    /**
     * 下载并解压 JDK
     * @param version JDK 版本
     * @param url 下载 URL
     * @param filename 文件名
     * @param destDir 目标目录
     * @return 解压后的 JDK 路径，如果失败则返回 null
     */
    private fun downloadAndExtractJdk(version: Int, url: String, filename: String, destDir: String): String? {
        try {
            val downloadPath = "$destDir${File.separator}$filename"
            val extractDir = "$destDir${File.separator}zulu$version"

            // 检查是否已经下载并解压
            if (File(extractDir).exists()) {
                println("Zulu JDK $version 已存在，跳过下载")
                // 返回 JDK 根目录
                return findJdkRootDir(extractDir)
            }

            println("正在下载 Zulu JDK $version...")
            // 静默下载 (使用 PowerShell)
            val downloadResult = "powershell -Command \"(New-Object Net.WebClient).DownloadFile('$url', '$downloadPath')\"".runCmd()
            if (!downloadResult.isSuccess()) {
                println("下载 Zulu JDK $version 失败: ${downloadResult.error}")
                return null
            }

            println("正在解压 Zulu JDK $version...")
            // 创建解压目录
            File(extractDir).mkdirs()
            // 解压文件 (使用 PowerShell)
            val extractResult = "powershell -Command \"Expand-Archive -Path '$downloadPath' -DestinationPath '$extractDir' -Force\"".runCmd()
            if (!extractResult.isSuccess()) {
                println("解压 Zulu JDK $version 失败: ${extractResult.error}")
                return null
            }

            // 删除下载的压缩文件
            File(downloadPath).delete()

            // 返回 JDK 根目录
            return findJdkRootDir(extractDir)
        } catch (e: Exception) {
            println("下载并解压 Zulu JDK $version 时出错: ${e.message}")
            return null
        }
    }

    /**
     * 查找 JDK 根目录
     * @param extractDir 解压目录
     * @return JDK 根目录路径
     */
    private fun findJdkRootDir(extractDir: String): String {
        val dir = File(extractDir)
        if (!dir.exists() || !dir.isDirectory) return extractDir

        // 查找包含 bin 目录的子目录
        dir.listFiles()?.forEach { file ->
            if (file.isDirectory && File(file, "bin").exists() && (File(file, "bin/java.exe").exists() || File(file, "bin/java").exists())) {
                return file.absolutePath
            }
        }

        // 如果没找到特定结构，返回解压目录
        return extractDir
    }

    /**
     * 配置 JAVA_HOME 环境变量 (Windows)
     * @param jdkPath JDK 路径
     */
    private fun configureJavaHome(jdkPath: String) {
        try {
            // 使用 PowerShell 设置用户环境变量
            val setUserEnvCommand = "powershell -Command \"[Environment]::SetEnvironmentVariable('JAVA_HOME', '$jdkPath', 'User')\""
            
            // 获取当前用户 PATH 并添加 JAVA_HOME/bin
            val updatePathCommand = """powershell -Command "[Environment]::SetEnvironmentVariable('PATH', '%JAVA_HOME%\\bin;' + [Environment]::GetEnvironmentVariable('PATH', 'User'), 'User')""""
            
            val result1 = setUserEnvCommand.runCmd()
            val result2 = updatePathCommand.runCmd()
            
            if (result1.isSuccess() && result2.isSuccess()) {
                println("JAVA_HOME 已配置为: $jdkPath")
                println("请重新打开命令提示符或 PowerShell 以使更改生效")
            } else {
                println("配置 JAVA_HOME 时出错")
            }
        } catch (e: Exception) {
            println("配置 JAVA_HOME 时出错: ${e.message}")
        }
    }

    /**
     * 检查是否为 Windows 平台
     * @return 是否为 Windows 平台
     */
    private fun isWindowsPlatform(): Boolean {
        return PlatformTools.getPlatformType() == PlatformType.WINDOWS
    }
}